/**	\author    coidgen 0.9.2
	\version    (4.0 build 25)
	\date      
	\brief     
*/

#ifndef __COID_CLIENT__maps_h
#define __COID_CLIENT__maps_h


#define CLIENT__maps_h



#include "coid/coidclient.h"
#include "coid/comm/sync/mutex_reg.h"


extern const version COID_version_maps_4_0;


 
#include "coid/comm/binstream/stlstream.h"

 
struct cMapImage
{
	std::string location;
	float minLat;
	float minLon;
	float maxLat;
	float maxLon;
	int coorX;
	int coorY;
	int zoom;
	
	friend binstream & operator << ( binstream & out, const cMapImage & x ) 	
	{ 
		return out << x.location << x.minLat << x.minLon << x.maxLat << x.maxLon << x.coorX << x.coorY << x.zoom; 
	};

	friend binstream & operator >> ( binstream & in, cMapImage & x ) 
	{
		return in >> x.location >> x.minLat >> x.minLon >> x.maxLat >> x.maxLon >> x.coorX >> x.coorY >> x.zoom;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const cMapImage & x )
    {
        MSTRUCT_OPEN(m,"mapImage");
		MM(m,"location",x.location);
		MM(m,"minLat",x.minLat);
		MM(m,"minLon",x.minLon);
		MM(m,"maxLat",x.maxLat);
		MM(m,"maxLon",x.maxLon);
		MM(m,"coorX",x.coorX);
		MM(m,"coorY",x.coorY);
		MM(m,"zoom",x.zoom);
		MSTRUCT_CLOSE(m);
    }
};

 
struct cConfiguration
{
	int imageHeight;
	int imageWidth;
	int maxHorizontalImagesCount;
	int maxVerticalImagesCount;
	int minZoom;
	int maxZoom;
	int actualZoom;
	cMapImage startImage;
	
	friend binstream & operator << ( binstream & out, const cConfiguration & x ) 	
	{ 
		return out << x.imageHeight << x.imageWidth << x.maxHorizontalImagesCount << x.maxVerticalImagesCount << x.minZoom << x.maxZoom << x.actualZoom << x.startImage; 
	};

	friend binstream & operator >> ( binstream & in, cConfiguration & x ) 
	{
		return in >> x.imageHeight >> x.imageWidth >> x.maxHorizontalImagesCount >> x.maxVerticalImagesCount >> x.minZoom >> x.maxZoom >> x.actualZoom >> x.startImage;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const cConfiguration & x )
    {
        MSTRUCT_OPEN(m,"configuration");
		MM(m,"imageHeight",x.imageHeight);
		MM(m,"imageWidth",x.imageWidth);	
		MM(m,"maxHorizontalImagesCount",x.maxHorizontalImagesCount);
		MM(m,"maxVerticalImagesCount",x.maxVerticalImagesCount);
		MM(m,"minZoom",x.minZoom);
		MM(m,"maxZoom",x.maxZoom);
		MM(m,"actualZoom",x.actualZoom);
		MM(m,"startImage",x.startImage);
		MSTRUCT_CLOSE(m);
    }
};

 
struct cImagePosition
{
	int cX;
	int cY;
	int zoom;
	float longitude;
	float latitude;
	
	friend binstream & operator << ( binstream & out, const cImagePosition & x ) 	
	{ 
		return out << x.cX << x.cY << x.zoom << x.longitude << x.latitude; 
	};

	friend binstream & operator >> ( binstream & in, cImagePosition & x ) 
	{
		return in >> x.cX >> x.cY >> x.zoom >> x.longitude >> x.latitude;      /// notice the FIFO order (first in, first out)
    };

	friend metastream& operator << ( metastream& m, const cImagePosition & x )
    {
        MSTRUCT_OPEN(m,"imagePosition");
		MM(m,"cX",x.cX);
		MM(m,"cY",x.cY);
		MM(m,"zoom",x.zoom);
		MM(m,"longitude",x.longitude);
		MM(m,"latitude",x.latitude);
		MSTRUCT_CLOSE(m);
    }

};




namespace coid {


struct COID_TABLE_maps_4_0;


class maps_client
{
private:
	COID_TABLE_maps_4_0 * _me;
	COID_TABLE_maps_4_0 * _vtbl;
	mutable comm_mutex_custom_reg<netstream, void*> _mx_reg;
	uint _conn_data;
	uint _timeout;
	charstr _addr;

	void set_connection_type( uint ct ) {_conn_data = ct;}
	void destroy_me();

public:
	maps_client();
	~maps_client();
	maps_client( const maps_client & c );
	maps_client & operator = ( const maps_client & c );

	opcd ping_server( const char * coid_address, uint coid_obj_id=UMAX, uint coid_flags=ConnectFlags::xACCESS_MODE ) const;
	bool is_connected() const {return _me != NULL;}
	opcd disconnect();
	const charstr& get_addr() const {return _addr;}
	comm_mutex_reg * get_mx() {return &_mx_reg;}
	opcd get_last_error() const;
	void set_last_error( opcd e );
	uint get_connection_type() const {return _conn_data;}
	opcd set_timeout( uint milliseconds );
	uint get_timeout() const {return _timeout;}
	void setup_stream( binstream& b, uint coid_flags, uint coid_obj_id ) const;
	bool setup_members( uint coid_stream_flags, netstream * bstream, binstream * bstream2=NULL, comm_mutex_reg * mx_reg=NULL );

	static const version & get_version() { return COID_version_maps_4_0; }


public:
	opcd connect(  int start_lat, int start_lon, int start_zoom, cConfiguration & configuration, const char * coid_address=NULL, uint coid_flags=ConnectFlags::xACCESS_MODE );
	opcd connect_within(  comm_mutex_reg & coid_channel, int start_lat, int start_lon, int start_zoom, cConfiguration & configuration );
	opcd connect_shared( uint coid_obj_id,  const char * coid_address=NULL, uint coid_flags=ConnectFlags::xACCESS_MODE  );

	opcd get_image_by_XY(cImagePosition & imagePosition, cMapImage & imageOut);
	opcd get_image_by_lon_lat(cImagePosition & imagePosition, cMapImage & imageOut);
	opcd change_zoom( cImagePosition & imagePosition, cConfiguration & configuration );
};

} // namespace coid


#endif	// ! __COID_CLIENT__maps_h
